package com.bmw.bingfa.service.impl;

import com.bmw.bingfa.dao.TicketOrderDao;
import com.bmw.bingfa.dao.TicketProductsDao;
import com.bmw.bingfa.dao.TicketUserDao;
import com.bmw.bingfa.model.TicketOrder;
import com.bmw.bingfa.model.TicketProducts;
import com.bmw.bingfa.model.TicketUser;
import com.bmw.bingfa.model.http.TicketReq;
import com.bmw.bingfa.service.TicketService;
import com.bmw.bingfa.util.ErrorMessage;
import com.bmw.bingfa.util.RedisUtil;
import com.bmw.bingfa.util.bean.BaseResponse;
import com.bmw.bingfa.util.bean.Constant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Classname: TicketServiceImpl
 * Package: com.bmw.bingfa.service.impl
 * Description:
 *
 * @Author 余集楠
 * @Create 2024/5/29 0029 17:22
 * @Version 1.8
 */
@Service
@Slf4j
public class TicketServiceImpl implements TicketService {
    @Autowired
    TicketOrderDao ticketOrderDao;
    @Autowired
    TicketProductsDao ticketProductsDao;
    @Autowired
    RedisUtil redisUtil;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse Order(TicketReq req) {

        //参数校验
        log.info("===[校验用户信息及商品信息]===");
        BaseResponse paramValidRes = validateParam(req.getProductId(), req.getUserId());
        if (paramValidRes.getCode() != 0) {
            return paramValidRes;
        }
        log.info("===[校验参数是否合法][通过]===");


        Long productId=req.getProductId(); //获取商品属性
        Long userId=req.getUserId();  //获取用户属性
        TicketProducts product=ticketProductsDao.selectByPrimaryKey(productId);
        //扣减库存
        product.setSaled(product.getSaled()+1);
        ticketProductsDao.updateByPrimaryKeySelective(product);
        //创建订单
        TicketOrder order=new TicketOrder();
        order.setUserId(userId);
        order.setProductId(productId);
        order.setProductName(product.getName());
        ticketOrderDao.insert(order);
        return BaseResponse.OK;
    }

    //加悲观锁防止并发
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse pOrder(TicketReq req) {
        log.info("===开始调用使用悲观锁的下单接口===");
        log.info("===校验用户信息，商品信息，库存信息===");
        BaseResponse paramValidRes=validateParamPessimistic(req.getProductId(),req.getUserId());
        if(paramValidRes.getCode()!=0){
            return paramValidRes;
        }
        log.info("===校验通过===");
        log.info("===校验用户是否重复下单===");
        TicketOrder param=new TicketOrder();
        param.setProductId(req.getProductId());
        param.setUserId(req.getUserId());
        List repeatCount=ticketOrderDao.listRepeatOrdersForUpdate(param);
        if(repeatCount.size()>0){
            log.error("===用户重复下单===");
            return BaseResponse.error(ErrorMessage.REPEAT_ORDER_ERROR);
        }
        log.info("===校验通过===");
        //开始下单
        Long productId=req.getProductId(); //获取商品属性
        Long userId=req.getUserId();  //获取用户属性
        TicketProducts product=ticketProductsDao.selectByPrimaryKey(productId);
        //扣减库存
        product.setSaled(product.getSaled()+1);
        ticketProductsDao.updateByPrimaryKeySelective(product);
        //创建订单
        TicketOrder order=new TicketOrder();
        order.setUserId(userId);
        order.setProductId(productId);
        order.setProductName(product.getName());
        ticketOrderDao.insert(order);
        return BaseResponse.OK;
    }

    private BaseResponse validateParamPessimistic(Long productId, Long userId) {
         //利用selectForUpdate锁定记录
         TicketProducts product=ticketProductsDao.selectForUpdate(productId);
         if(product==null){
             log.error("===门票不存在===");
             return BaseResponse.error(ErrorMessage.SYS_ERROR);
         }
         if(product.getSaled()>=product.getCount()){
             log.error("===门票库存不足===");
             return BaseResponse.error(ErrorMessage.STOCK_NOT_ENOUGH);
         }
         return BaseResponse.OK;
    }

    private BaseResponse validateParam(Long productId, Long userId) {
        TicketProducts product = ticketProductsDao.selectByPrimaryKey(productId);
        if (product == null) {
            log.error("===[产品不存在！]===");
            return BaseResponse.error(ErrorMessage.SYS_ERROR);
        }
        if (product.getSaled() >= product.getCount()) {
            log.error("===[库存不足！]===");
            return BaseResponse.error(ErrorMessage.STOCK_NOT_ENOUGH);
        }
        if (hasOrderedUserCache(productId, userId)) {
            log.error("===[用户重复下单！]===");
            return BaseResponse.error(ErrorMessage.REPEAT_ORDER_ERROR);
        }
        return BaseResponse.OK;
    }

    private boolean hasOrderedUserCache(Long productId, Long userId) {
        String key = String.format(Constant.redisKey.SECKILL_ORDERED_USER, productId);
        return redisUtil.sHasKey(key, userId);
    }
}
